﻿ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

using Qing.Lang;
using System.Security.Cryptography.X509Certificates;

namespace Qing.Std {

    class MathAbs : Native {
        public override string Name { get; set; } = "绝对值";
        public override string Desc { get; set; } = "参数1-数字，返回数字；返回参数1数字的绝对值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@绝对值函数参数不足");
            }
            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Int, Math.Abs(args[0].Int()));
            }else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, Math.Abs(args[0].Float()));
            }

            return Expr.Err("#数学库@绝对值函数参数类型错误");
        }

    }

    class MathMax : Native {
        public override string Name { get; set; } = "最大值";
        public override string Desc { get; set; } = "不定参数-数字，返回数字；传入任意个数的数字，返回其中的最大值";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@最大值函数参数不足");
            }
            
            int idx = 0;
            int maxIdx = 0;
            decimal maxVal = decimal.MinValue;
            if(args.Count > 0 && args[0].Tp == TP.Arr) {
                var arr = args[0].List!;
                while (idx < args[0].List!.Count) {
                    if (arr[idx].Tp != TP.Int && arr[idx].Tp != TP.Float) {
                        return Expr.Err("#数学库@最大值函数参数类型错误");
                    }

                    if (arr[idx].Tp == TP.Int) {
                        if ((decimal)arr[idx].Int() > maxVal) {
                            maxVal = (decimal)arr[idx].Int();
                            maxIdx = idx;
                        }
                    } else if (arr[idx].Tp == TP.Float) {
                        if (arr[idx].Float() > maxVal) {
                            maxVal = arr[idx].Float();
                            maxIdx = idx;
                        }
                    }
                    idx++;
                }
                return arr[maxIdx].Dup();
            }

            while(idx < args.Count) {
                if (args[idx].Tp != TP.Int && args[idx].Tp != TP.Float) {
                    return Expr.Err("#数学库@最大值函数参数类型错误");
                }

                if (args[idx].Tp == TP.Int) {
                    if ((decimal)args[idx].Int() > maxVal) {
                        maxVal = (decimal)args[idx].Int();
                        maxIdx = idx;
                    }
                }else if (args[idx].Tp == TP.Float) {
                    if (args[idx].Float() > maxVal) {
                        maxVal = args[idx].Float();
                        maxIdx = idx;
                    }
                }
                idx++;
            }

            return args[maxIdx].Dup();
        }

    }


    class MathMin : Native {
        public override string Name { get; set; } = "最小值";
        public override string Desc { get; set; } = "不定参数-数字，返回数字；传入任意个数的数字，返回其中的最小值";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@最小值函数参数不足");
            }

            int idx = 0;
            int minIdx = 0;
            decimal minVal = decimal.MaxValue;

            if (args.Count > 0 && args[0].Tp == TP.Arr) {
                var arr = args[0].List!;
                while (idx < args[0].List!.Count) {
                    if (arr[idx].Tp != TP.Int && arr[idx].Tp != TP.Float) {
                        return Expr.Err("#数学库@最小值函数参数类型错误");
                    }

                    if (arr[idx].Tp == TP.Int) {
                        if ((decimal)arr[idx].Int() < minVal) {
                            minVal = (decimal)arr[idx].Int();
                            minIdx = idx;
                        }
                    } else if (arr[idx].Tp == TP.Float) {
                        if (arr[idx].Float() < minVal) {
                            minVal = arr[idx].Float();
                            minIdx = idx;
                        }
                    }
                    idx++;
                }
                return arr[minIdx].Dup();
            }

            while (idx < args.Count) {
                if (args[idx].Tp != TP.Int && args[idx].Tp != TP.Float) {
                    return Expr.Err("#数学库@最小值函数参数类型错误");
                }

                if (args[idx].Tp == TP.Int) {
                    if ((decimal)args[idx].Int() < minVal) {
                        minVal = (decimal)args[idx].Int();
                        minIdx = idx;
                    }
                } else if (args[idx].Tp == TP.Float) {
                    if (args[idx].Float() < minVal) {
                        minVal = args[idx].Float();
                        minIdx = idx;
                    }
                }
                idx++;
            }

            return args[minIdx].Dup();
        }

    }


    class MathFloor : Native {
        public override string Name { get; set; } = "向下取整";
        public override string Desc { get; set; } = "参数1-小数，返回整数；返回参数1数字向下取整的整数";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@向下取整函数参数不足");
            }

            if (args[0].Tp == TP.Float) {
                return new Expr(TP.Int, (int)Math.Floor(args[0].Float()));
            }

            return Expr.Err("#数学库@向下取整函数参数错误");

        }

    }

    class MathCeil : Native {
        public override string Name { get; set; } = "向上取整";
        public override string Desc { get; set; } = "参数1-小数，返回整数；返回参数1数字向上取整的整数";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@向上取整函数参数不足");
            }

            if (args[0].Tp == TP.Float) {
                return new Expr(TP.Int, (int)Math.Ceiling(args[0].Float()));
            }

            return Expr.Err("#数学库@向上取整函数参数错误");

        }

    }


    class MathRound : Native {
        public override string Name { get; set; } = "四舍五入";
        public override string Desc { get; set; } = "参数1-小数，返回整数；返回参数1数字四舍五入的整数";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@四舍五入函数参数不足");
            }

            if (args[0].Tp == TP.Float) {
                if (args.Count == 1) {
                    return new Expr(TP.Int, (int)Math.Round(args[0].Float()));
                }else if(args.Count > 1 && args[1].Tp == TP.Int) {
                    return new Expr(TP.Float, Math.Round(args[0].Float(), args[1].Int()));
                }
                
            }

            return Expr.Err("#数学库@四舍五入函数参数错误");

        }

    }


    class MathPow : Native {
        public override string Name { get; set; } = "乘方";
        public override string Desc { get; set; } = "参数1-数字，参数2-数字，返回数字；返回参数1数字的参数2数字的幂";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count < 2) {
                return Expr.Err("#数学库@乘方函数参数不足");
            }

            return Op.Power(args, ctx);

        }

    }


    class MathSqrt : Native {
        public override string Name { get; set; } = "平方根";
        public override string Desc { get; set; } = "参数1-数字，返回数字；返回参数1数字开平方根的值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@平方根函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)Math.Sqrt((double)args[0].Int()));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)Math.Sqrt((double)args[0].Float()));
            }


            return Expr.Err("#数学库@平方根函数参数错误");
        }

    }


    class MathRandom : Native {
        public override string Name { get; set; } = "随机数";
        public override string Desc { get; set; } = "可选参数1-数字，可选参数2-数字，返回数字；传入1个整数或小数N时，返回0到N的随机数；传入2个整数时，返回两个整数之间的随机数";

        public static Random random = new Random(DateTime.Now.Millisecond);

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count == 1) {
                if (args[0].Tp == TP.Int) {
                    return new Expr(TP.Int, random.Next(args[0].Int()));
                } else if (args[0].Tp == TP.Float) {
                    return new Expr(TP.Float, (decimal)(random.NextDouble()) * args[0].Float());
                }
            }
            if (args.Count == 2 && args[0].Tp == TP.Int && args[1].Tp == TP.Int) {
                return new Expr(TP.Int, random.Next(args[0].Int(), args[1].Int()));
            }

            return new Expr(TP.Int, random.Next());

        }

    }


    class MathRandomSeek : Native {
        public override string Name { get; set; } = "随机数种子";
        public override string Desc { get; set; } = "参数1-数字，返回逻辑；传入1个整数作为随机数种子";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {

            if (args[0].Tp == TP.Int) {
                MathRandom.random = new Random(args[0].Int());
                return new Expr(TP.Bool, true);
            } 

            return Expr.Err("#数学库@随机数种子函数只接受整数类型的参数");

        }

    }


    class MathTan : Native {
        public override string Name { get; set; } = "tan";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入角度，计算tan值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@tan函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)Math.Tan(args[0].Int() * Math.PI / 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)Math.Tan((double)args[0].Float() * Math.PI / 180));
            }

            return Expr.Err("#数学库@tan函数参数错误");

        }

    }

    class MathSin : Native {
        public override string Name { get; set; } = "sin";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入角度，计算sin值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@sin函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)Math.Sin(args[0].Int() * Math.PI / 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)Math.Sin((double)args[0].Float() * Math.PI / 180));
            }

            return Expr.Err("#数学库@sin函数参数错误");

        }

    }

    class MathCos : Native {
        public override string Name { get; set; } = "cos";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入角度，计算cos值";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@cos函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)Math.Cos(args[0].Int() * Math.PI / 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)Math.Cos((double)args[0].Float() * Math.PI / 180));
            }

            return Expr.Err("#数学库@cos函数参数错误");

        }

    }

    class MathAtan : Native {
        public override string Name { get; set; } = "atan";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入比值，通过atan计算角度";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@atan函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)(Math.Atan(args[0].Int()) / Math.PI * 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)(Math.Atan((double)args[0].Float()) / Math.PI * 180));
            }

            return Expr.Err("#数学库@atan函数参数错误");

        }

    }

    class MathAsin : Native {
        public override string Name { get; set; } = "asin";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入比值，通过asin计算角度";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@asin函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)(Math.Asin(args[0].Int()) / Math.PI * 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)(Math.Asin((double)args[0].Float()) / Math.PI * 180));
            }

            return Expr.Err("#数学库@asin函数参数错误");

        }

    }

    class MathAcos : Native {
        public override string Name { get; set; } = "acos";
        public override string Desc { get; set; } = "参数1-整数|小数，返回小数；传入比值，通过acos计算角度";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            if (args.Count == 0) {
                return Expr.Err("#数学库@acos函数参数不足");
            }

            if (args[0].Tp == TP.Int) {
                return new Expr(TP.Float, (decimal)(Math.Acos(args[0].Int()) / Math.PI * 180));
            } else if (args[0].Tp == TP.Float) {
                return new Expr(TP.Float, (decimal)(Math.Acos((double)args[0].Float()) / Math.PI * 180));
            }

            return Expr.Err("#数学库@acos函数参数错误");

        }

    }


}
